//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

#include "pch.h"
#include "Scenario1_CachedNetworks.xaml.h"

using namespace SDKTemplate;
using namespace SDKTemplate::WiFiScan;

using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Globalization::DateTimeFormatting;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace concurrency;
using namespace Windows::Devices::WiFi;

Scenario1_CachedNetworks::Scenario1_CachedNetworks() : _rootPage(MainPage::Current)
{
    InitializeComponent();
}

void Scenario1_CachedNetworks::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    auto button = (Button^)sender;
    auto index = (int)button->Tag;

    // Accessing the NetworkReport property from the WiFiAdapter does not trigger any scans.
    // The NetworkReport will have the report generated by the last scan on the system; the
    // scan need not be generated by the app.
    DisplayNetworkReport(_wiFiAdapters->GetAt(index)->NetworkReport, _wiFiAdapters->GetAt(index));
}

void Scenario1_CachedNetworks::OnNavigatedTo(NavigationEventArgs^ e)
{
    ResultCollection = ref new Vector<WiFiNetworkDisplay^>();
    DataContext = this;

    // RequestAccessAsync must have been called at least once by the app before using the API
    // Calling it multiple times is fine but not necessary
    // RequestAccessAsync must be called from the UI thread
    auto requestAccessOperation = WiFiAdapter::RequestAccessAsync();
    auto requestAccessTask = create_task(requestAccessOperation);

    requestAccessTask.then([this](WiFiAccessStatus result)
    {
        if (result != WiFiAccessStatus::Allowed)
        {
            _rootPage->NotifyUser(L"Access denied", SDKTemplate::NotifyType::ErrorMessage);
        }
        else
        {
            auto wiFiAdaptersOperation = WiFiAdapter::FindAllAdaptersAsync();
            auto wiFiAdaptersTask = create_task(wiFiAdaptersOperation);

            wiFiAdaptersTask.then([this](IVectorView<WiFiAdapter^>^ adapters)
            {
                _wiFiAdapters = adapters;

                int index = 0;
                for (auto adapter : _wiFiAdapters)
                {
                    auto button = ref new Button();
                    button->Tag = index;

                    button->Content = L"WiFi Adapter " + (++index);
                    button->Click += ref new RoutedEventHandler(this, &Scenario1_CachedNetworks::Button_Click);
                    Buttons->Children->Append(button);
                }
            });
        }
    });
}

void Scenario1_CachedNetworks::DisplayNetworkReport(WiFiNetworkReport^ report, WiFiAdapter^ adapter)
{
    auto timestampString = DateTimeFormatter::LongDate->Format(report->Timestamp);
    auto message = L"Network Report Timestamp: " + timestampString;
    // there is no guarantee of what thread the AvailableNetworksChanged callback is run on
    _rootPage->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,
        ref new DispatchedHandler([this, message]
    {
        _rootPage->NotifyUser(message, SDKTemplate::NotifyType::StatusMessage);
    }));

    ResultCollection->Clear();
    for (auto network : report->AvailableNetworks)
    {
        ResultCollection->Append(ref new WiFiNetworkDisplay(network, adapter));
    }
}
